<script lang="ts" setup>
import { ref } from 'vue'
import CryptoJS from 'crypto-js'
import JSEncrypt from 'jsencrypt'

const plainText = ref('')
const encryptedText = ref('')
const decryptedText = ref('')
const publicKey = ref('')
const privateKey = ref('')
const keySize = ref('2048')
const errorMessage = ref('')
const isSuccess = ref(false)


const keySizes = [1024, 2048, 3072, 4096]

// 生成RSA密钥对
function generateKeyPair() {
  try {
    const crypt = new JSEncrypt({ default_key_size: keySize.value })
    
    // 生成密钥对
    const keyPair = crypt.getKey()
    
    if (keyPair) {
      publicKey.value = keyPair.getPublicKey()
      privateKey.value = keyPair.getPrivateKey()
      
      errorMessage.value = `${keySize.value}位RSA密钥对生成成功 ✓`
      isSuccess.value = true
    } else {
      errorMessage.value = '密钥对生成失败'
      isSuccess.value = false
    }
  } catch (error) {
    errorMessage.value = `密钥对生成失败: ${(error as Error).message}`
    isSuccess.value = false
  }
}

// RSA加密
function encryptText() {
  try {
    if (!plainText.value.trim()) {
      errorMessage.value = '请输入要加密的文本'
      isSuccess.value = false
      return
    }
    
    if (!publicKey.value.trim()) {
      errorMessage.value = '请输入公钥'
      isSuccess.value = false
      return
    }
    
    const encrypt = new JSEncrypt()
    encrypt.setPublicKey(publicKey.value)
    
    const encrypted = encrypt.encrypt(plainText.value)
    
    if (encrypted) {
      encryptedText.value = encrypted
      errorMessage.value = 'RSA加密成功 ✓'
      isSuccess.value = true
    } else {
      errorMessage.value = 'RSA加密失败，请检查公钥格式或文本长度'
      isSuccess.value = false
    }
  } catch (error) {
    errorMessage.value = `RSA加密失败: ${(error as Error).message}`
    isSuccess.value = false
    encryptedText.value = ''
  }
}

// RSA解密
function decryptText() {
  try {
    if (!encryptedText.value.trim()) {
      errorMessage.value = '请输入要解密的密文'
      isSuccess.value = false
      return
    }
    
    if (!privateKey.value.trim()) {
      errorMessage.value = '请输入私钥'
      isSuccess.value = false
      return
    }
    
    const decrypt = new JSEncrypt()
    decrypt.setPrivateKey(privateKey.value)
    
    const decrypted = decrypt.decrypt(encryptedText.value)
    
    if (decrypted) {
      decryptedText.value = decrypted
      errorMessage.value = 'RSA解密成功 ✓'
      isSuccess.value = true
    } else {
      errorMessage.value = 'RSA解密失败，请检查私钥和密文是否匹配'
      isSuccess.value = false
    }
  } catch (error) {
    errorMessage.value = `RSA解密失败: ${(error as Error).message}`
    isSuccess.value = false
    decryptedText.value = ''
  }
}



// 复制到剪贴板
function copyToClipboard(text: string, type: string) {
  if (text) {
    navigator.clipboard.writeText(text).then(() => {
      errorMessage.value = `${type}已复制到剪贴板 ✓`
      isSuccess.value = true
    })
  }
}

// 清空所有
function clearAll() {
  plainText.value = ''
  encryptedText.value = ''
  decryptedText.value = ''
  errorMessage.value = ''
  isSuccess.value = false
}

// 清空密钥
function clearKeys() {
  publicKey.value = ''
  privateKey.value = ''
  errorMessage.value = '密钥已清空 ✓'
  isSuccess.value = true
}

// 加载示例
function loadSample() {
  plainText.value = 'Hello, World! 这是一个RSA加密测试文本。'
  
  // 生成示例密钥对
  generateKeyPair()
}

// 交换加密解密文本
function swapTexts() {
  const temp = plainText.value
  plainText.value = decryptedText.value
  decryptedText.value = temp
  
  encryptedText.value = ''
  errorMessage.value = '文本已交换 ✓'
  isSuccess.value = true
}

// 导出密钥
function exportKeys() {
  if (!publicKey.value && !privateKey.value) {
    errorMessage.value = '没有可导出的密钥'
    isSuccess.value = false
    return
  }
  
  const keyData = {
    keySize: keySize.value,
    publicKey: publicKey.value,
    privateKey: privateKey.value,
    generatedAt: new Date().toISOString()
  }
  
  const blob = new Blob([JSON.stringify(keyData, null, 2)], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `rsa_keys_${keySize.value}.json`
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  URL.revokeObjectURL(url)
  
  errorMessage.value = '密钥导出成功 ✓'
  isSuccess.value = true
}
</script>

<template>
  <div class="rsa-tool">
    <div class="config-section">
      <h3>RSA配置</h3>
      <div class="config-grid">
        <div class="config-item">
          <label>密钥长度:</label>
          <select v-model="keySize" class="config-select">
            <option v-for="size in keySizes" :key="size" :value="size">
              {{ size }}位
            </option>
          </select>
        </div>
        

      </div>
    </div>

    <div class="key-section">
      <h3>RSA密钥管理</h3>
      <div class="key-controls">
        <button class="btn btn-primary" @click="generateKeyPair">🔑 生成密钥对</button>
        <button class="btn btn-info" @click="exportKeys" :disabled="!publicKey && !privateKey">💾 导出密钥</button>
        <button class="btn btn-danger" @click="clearKeys">🗑️ 清空密钥</button>
      </div>
      
      <div class="key-grid">
        <div class="key-item">
          <label>公钥 (用于加密和验签):</label>
          <div class="key-textarea-wrapper">
            <textarea 
              v-model="publicKey" 
              class="key-textarea"
              placeholder="请输入或生成RSA公钥..."
              spellcheck="false"
            ></textarea>
            <button 
              class="btn btn-success btn-sm copy-btn" 
              @click="copyToClipboard(publicKey, '公钥')"
              :disabled="!publicKey"
            >
              📋
            </button>
          </div>
        </div>
        
        <div class="key-item">
          <label>私钥 (用于解密和签名):</label>
          <div class="key-textarea-wrapper">
            <textarea 
              v-model="privateKey" 
              class="key-textarea"
              placeholder="请输入或生成RSA私钥..."
              spellcheck="false"
            ></textarea>
            <button 
              class="btn btn-success btn-sm copy-btn" 
              @click="copyToClipboard(privateKey, '私钥')"
              :disabled="!privateKey"
            >
              📋
            </button>
          </div>
        </div>
      </div>
    </div>

    <div class="controls">
      <button class="btn btn-primary" @click="encryptText">🔒 加密</button>
      <button class="btn btn-primary" @click="decryptText">🔓 解密</button>

      <button class="btn btn-info" @click="swapTexts">🔄 交换文本</button>
      <button class="btn btn-warning" @click="loadSample">📝 加载示例</button>
      <button class="btn btn-danger" @click="clearAll">🗑️ 清空</button>
    </div>

    <div class="status" v-if="errorMessage" :class="{ 'error': !isSuccess, 'success': isSuccess }">
      {{ errorMessage }}
    </div>

    <div class="operation-tabs">
      <div class="tab-container">
        <div class="tab-header">
          <button class="tab-btn active" data-tab="encrypt">加密解密</button>
        </div>
        
        <div class="tab-content">
          <div class="tab-panel active" data-panel="encrypt">
            <div class="editor-container">
              <div class="editor-section">
                <h3>原文</h3>
                <div class="textarea-wrapper">
                  <textarea 
                    v-model="plainText" 
                    class="text-input"
                    placeholder="请输入要加密的文本...\n\n注意：RSA加密有长度限制，建议文本长度不超过密钥长度的1/8"
                    spellcheck="false"
                  ></textarea>
                  <button 
                    class="btn btn-success btn-sm copy-btn" 
                    @click="copyToClipboard(plainText, '原文')"
                    :disabled="!plainText"
                  >
                    📋
                  </button>
                </div>
              </div>

              <div class="editor-section">
                <h3>密文</h3>
                <div class="textarea-wrapper">
                  <textarea 
                    v-model="encryptedText" 
                    class="text-output"
                    placeholder="加密后的密文将显示在这里..."
                    spellcheck="false"
                  ></textarea>
                  <button 
                    class="btn btn-success btn-sm copy-btn" 
                    @click="copyToClipboard(encryptedText, '密文')"
                    :disabled="!encryptedText"
                  >
                    📋
                  </button>
                </div>
              </div>

              <div class="editor-section">
                <h3>解密结果</h3>
                <div class="textarea-wrapper">
                  <textarea 
                    v-model="decryptedText" 
                    class="text-output"
                    placeholder="解密后的文本将显示在这里..."
                    readonly
                    spellcheck="false"
                  ></textarea>
                  <button 
                    class="btn btn-success btn-sm copy-btn" 
                    @click="copyToClipboard(decryptedText, '解密结果')"
                    :disabled="!decryptedText"
                  >
                    📋
                  </button>
                </div>
              </div>
            </div>
          </div>
          

        </div>
      </div>
    </div>

    <div class="help-section">
      <details>
        <summary>RSA加密说明</summary>
        <div class="help-content">
          <h4>RSA加密特点:</h4>
          <ul>
            <li><strong>非对称加密:</strong> 使用公钥加密，私钥解密</li>
            <li><strong>密钥长度:</strong> 推荐使用2048位或更高，1024位已不安全</li>
            <li><strong>加密长度限制:</strong> 明文长度不能超过密钥长度减去填充长度</li>
          </ul>
          <h4>使用场景:</h4>
          <ul>
            <li><strong>密钥交换:</strong> 安全传输对称加密密钥</li>
            <li><strong>小数据加密:</strong> 加密少量敏感数据</li>
          </ul>
          <h4>安全建议:</h4>
          <ul>
            <li>私钥必须严格保密，不能泄露</li>
            <li>公钥可以公开分发</li>
            <li>定期更换密钥对</li>
            <li>大量数据建议使用混合加密（RSA+AES）</li>
            <li>本工具仅提供基础的RSA加密解密功能</li>
          </ul>
        </div>
      </details>
    </div>
  </div>
</template>

<style scoped>
.rsa-tool {
  width: 100%;
}

.config-section,
.key-section {
  margin-bottom: 20px;
  padding: 20px;
  background: rgba(255, 255, 255, 0.05);
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.config-section h3,
.key-section h3 {
  margin: 0 0 15px 0;
  color: #fff;
  font-size: 1.1em;
}

.config-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
}

.config-item {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.config-item label {
  color: #ccc;
  font-size: 14px;
  font-weight: 500;
}

.config-select {
  padding: 8px 12px;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 4px;
  color: #fff;
  font-size: 14px;
  outline: none;
}

.config-select:focus {
  border-color: rgba(255, 255, 255, 0.4);
}

.key-controls {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}

.key-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}

.key-item {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.key-item label {
  color: #ccc;
  font-size: 14px;
  font-weight: 500;
}

.key-textarea-wrapper {
  position: relative;
  height: 150px;
}

.key-textarea {
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 6px;
  padding: 12px;
  color: #fff;
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 12px;
  line-height: 1.4;
  resize: none;
  outline: none;
}

.key-textarea:focus {
  border-color: rgba(255, 255, 255, 0.4);
}

.key-textarea::placeholder {
  color: rgba(255, 255, 255, 0.5);
}

.controls {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}

.btn {
  padding: 8px 16px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  transition: all 0.2s ease;
  color: #fff;
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-sm {
  padding: 4px 8px;
  font-size: 12px;
}

.btn-primary {
  background: #007bff;
}

.btn-primary:hover:not(:disabled) {
  background: #0056b3;
}

.btn-secondary {
  background: #6c757d;
}

.btn-secondary:hover:not(:disabled) {
  background: #545b62;
}

.btn-success {
  background: #28a745;
}

.btn-success:hover:not(:disabled) {
  background: #1e7e34;
}

.btn-info {
  background: #17a2b8;
}

.btn-info:hover:not(:disabled) {
  background: #117a8b;
}

.btn-warning {
  background: #ffc107;
  color: #212529;
}

.btn-warning:hover:not(:disabled) {
  background: #e0a800;
}

.btn-danger {
  background: #dc3545;
}

.btn-danger:hover:not(:disabled) {
  background: #c82333;
}

.status {
  padding: 12px;
  border-radius: 6px;
  margin-bottom: 20px;
  font-weight: 500;
}

.status.error {
  background: rgba(220, 53, 69, 0.1);
  color: #dc3545;
  border: 1px solid rgba(220, 53, 69, 0.3);
}

.status.success {
  background: rgba(40, 167, 69, 0.1);
  color: #28a745;
  border: 1px solid rgba(40, 167, 69, 0.3);
}

.operation-tabs {
  margin-bottom: 20px;
}

.tab-container {
  background: rgba(255, 255, 255, 0.05);
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  overflow: hidden;
}

.tab-header {
  display: flex;
  background: rgba(0, 0, 0, 0.2);
}

.tab-btn {
  flex: 1;
  padding: 12px 20px;
  background: transparent;
  border: none;
  color: #ccc;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s ease;
}

.tab-btn:hover {
  background: rgba(255, 255, 255, 0.05);
  color: #fff;
}

.tab-btn.active {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  border-bottom: 2px solid #007bff;
}

.tab-content {
  padding: 20px;
}

.tab-panel {
  display: none;
}

.tab-panel.active {
  display: block;
}

.editor-container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 20px;
}

.editor-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.editor-section h3 {
  margin: 0;
  color: #fff;
  font-size: 1.1em;
}

.textarea-wrapper {
  position: relative;
  height: 200px;
}

.text-input,
.text-output {
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 6px;
  padding: 12px;
  color: #fff;
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
  resize: none;
  outline: none;
}

.text-output {
  background: rgba(0, 0, 0, 0.4);
}

.text-input:focus,
.text-output:focus {
  border-color: rgba(255, 255, 255, 0.4);
}

.text-input::placeholder,
.text-output::placeholder {
  color: rgba(255, 255, 255, 0.5);
}

.copy-btn {
  position: absolute;
  top: 8px;
  right: 8px;
}

.verify-result {
  height: 200px;
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 6px;
  padding: 12px;
  color: #ccc;
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.verify-result.valid {
  color: #28a745;
  border-color: rgba(40, 167, 69, 0.5);
  background: rgba(40, 167, 69, 0.1);
}

.verify-result.invalid {
  color: #dc3545;
  border-color: rgba(220, 53, 69, 0.5);
  background: rgba(220, 53, 69, 0.1);
}

.help-section {
  margin-top: 20px;
}

.help-section details {
  background: rgba(255, 255, 255, 0.05);
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.help-section summary {
  padding: 12px 15px;
  cursor: pointer;
  color: #fff;
  font-weight: 500;
  user-select: none;
}

.help-section summary:hover {
  background: rgba(255, 255, 255, 0.05);
}

.help-content {
  padding: 15px;
  color: #ccc;
}

.help-content h4 {
  margin: 0 0 10px 0;
  color: #fff;
  font-size: 1em;
}

.help-content ul {
  margin: 0 0 15px 0;
  padding-left: 20px;
}

.help-content li {
  margin-bottom: 5px;
  line-height: 1.4;
}

.help-content strong {
  color: #fff;
}

@media (max-width: 768px) {
  .config-grid {
    grid-template-columns: 1fr;
  }
  
  .key-grid {
    grid-template-columns: 1fr;
  }
  
  .editor-container {
    grid-template-columns: 1fr;
  }
  
  .controls,
  .key-controls {
    justify-content: center;
  }
  
  .tab-header {
    flex-direction: column;
  }
}
</style>